package cn.how2go.net.server.util;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2018/4/13.
 */
public class BinaryUtil {
    public static long sendCount = 0L;

    /**
     * 将8位bit组成一个byte
     * @param bit
     * @return
     */
    public static byte groupByte(boolean[] bit){
        byte result = 0;
        for(int i=0;i<bit.length;i++){
            if(bit[i]){
                result |= 1 << i;
            }
        }
        return result;
    }

    /**
     * 高位在前面
     * @param data
     * @return
     */
    public static int getMsgHead(byte... data){
        int result = 0;
        for(int i=0;i<data.length;i++){
            int a = (data[data.length-1-i] & 0xff) << (8*i);
            result = result | a ;
        }
        return result;
    }

    public static byte[] createMsgHead(int prefix,int length){
        byte[] result = new byte[length];
        if(length == 4) {
            for (int i = 0; i < length; i++) {
                if (i == 0) {
                    result[i] = (byte) ((0xff000000 & prefix) >> 24);
                }
                if (i == 1) {
                    result[i] = (byte) ((0x00ff0000 & prefix) >> 16);
                }
                if (i == 2) {
                    result[i] = (byte) ((0x0000ff00 & prefix) >> 8);
                }
                if (i == 3) {
                    result[i] = (byte) (0x000000ff & prefix);
                }
            }
        }
        if(length == 3) {
            for (int i = 0; i < length; i++) {
                if (i == 0) {
                    result[i] = (byte) ((0x00ff0000 & prefix) >> 16);
                }
                if (i == 1) {
                    result[i] = (byte) ((0x0000ff00 & prefix) >> 8);
                }
                if (i == 2) {
                    result[i] = (byte) (0x000000ff & prefix);
                }
            }
        }
        if(length == 2) {
            for (int i = 0; i < length; i++) {
                if (i == 0) {
                    result[i] = (byte) ((0x0000ff00 & prefix) >> 8);
                }
                if (i == 1) {
                    result[i] = (byte) (0x000000ff & prefix);
                }
            }
        }
        if(length == 1){
            result[0] = (byte) (0x000000ff & prefix);
        }
        return result;
    }

    public static byte GetCheckXor(byte[] data, int pos, int len) {
        byte A = 0;
        for (int i = pos; i < len; i++) {
            A ^= data[i];
        }
        return A;
    }

    public static byte[] GetBytes(byte[] data, int pos, int len) {
        byte[] A = new byte[len];
        int j =0;
        for (int i = pos; i < pos+len; i++) {
            A[j] = data[i];
            j++;
        }
        return A;
    }

    public static short pareShort(byte[] data){
        int result = 0;
        if(data.length == 2){
            int a = (data[0] & 0xff) << 8;
            int b = (data[1] & 0xff);
            result = a | b ;
        }
        return (short)result;
    }

    public static int pareInt(byte[] data){
        int result = 0;
        if(data.length == 2){
            int a = (data[0] & 0xff) << 8;
            int b = (data[1] & 0xff);
            result = a | b ;
        }
        return result;
    }

    public static String bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[ i ] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    public static long getSendCount() {
        if (sendCount > 1000000000L)
            sendCount = 1L;
        else {
            sendCount += 1L;
        }
        return sendCount;
    }

    public static String turnDataLength(String data, int length) {
        int data_length = data.length();
        for (int i = data_length; i < length; i++) {
            data = "0" + data;
        }
        return data;
    }

    public static String turnStrLength(String data, int length) {
        int data_length = data.length();
        for (int i = data_length; i < length; i++) {
            data = data + "0";
        }
        return data;
    }

    public static String ToHexString(byte[] bts) {
        StringBuilder strBuild = new StringBuilder();

        for (int i = 0; i < bts.length; i++) {
            strBuild.append(ToHexString(bts[i]));
        }
        return strBuild.toString();
    }
    //加空格 用于阅读输出
    public static String ToHexFormatString(byte[] bts) {
        StringBuilder strBuild = new StringBuilder();

        for (int i = 0; i < bts.length; i++) {
            strBuild.append(ToHexString(bts[i])).append(" ");
        }
        return strBuild.toString();
    }


    public static String hex2Ascii(String hex) {
        String result = "";
        int len = hex.length() / 2;
        for (int i = 0; i < len; i++) {
            int tmp = Integer.valueOf(hex.substring(2 * i, 2 * i + 2), 16)
                    .intValue();
            result = result + (char) tmp;
        }
        return result;
    }

    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;

        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);

            b[i] = ((byte) (parse(c0) << 4 | parse(c1)));
            //int start = i * 2;
            //int c = Integer.parseInt(hexstr.substring(start, start + 2));
            //b[i] = (byte)c;
        }

        return b;
    }

    private static int parse(char c) {
        if (c >= 'a') {
            return c - 'a' + 10 & 0xF;
        }

        if (c >= 'A') {
            return c - 'A' + 10 & 0xF;
        }

        return c - '0' & 0xF;
    }

    public static String TurnISN(String str) {
        String str1 = "";
        byte[] b = (byte[]) null;
        try {
            b = str.getBytes("gbk");
        } catch (UnsupportedEncodingException e) {
            System.out.println("异常信息(ControllerReport TurnISN)"
                    + e.getMessage());
        }
        System.out.println();
        int i = 0;
        for (int max = b.length; i < max; i++) {
            str1 = str1 + Integer.toHexString(b[i] & 0xFF);
        }
        return str1.toUpperCase();
    }

    // 将数字转换成16进制字符串，不足补零
    public static String ToHexString(byte data) {
        return Integer.toHexString(data & 0xff | 0x100).substring(1);
    }

    // 将数字转换成16进制字符串，不足补零
    public static String ToHexString(Short data) {
        return Integer.toHexString(data & 0xffff | 0x10000).substring(1);
    }

    public static String ToHexString(long val) {
        String tmp = Long.toHexString(val);
        StringBuilder sb = new StringBuilder("0000000000000000");
        sb.replace(16 - tmp.length(), 16, tmp);
        return sb.toString();
    }

    // 将数字转换成16进制字符串，不足补零
    public static String ToHexString(int data) {
        String tmp = Integer.toHexString(data);
        StringBuilder sb = new StringBuilder("00000000");
        sb.replace(8 - tmp.length(), 8, tmp);
        return sb.toString();
    }

    public static String ToHexString(long data, int byteNum) {

        StringBuilder sb = new StringBuilder("");
        for (int m = 0; m < byteNum; m++) {
            sb.append("00");
        }
        int totalLen = byteNum * 2;
        String tmp = Long.toHexString(data);
        sb.replace(totalLen - tmp.length(), totalLen, tmp);
        return sb.toString();
    }

    /**
     * 将字符串转换成16进制串
     */
    public static String ToHexString(String str) {
        String str1 = "";
        try {
            byte[] b = str.getBytes("gbk");
            int i = 0;
            int max = b.length;
            for (; i < max; i++) {
                str1 = str1 + Integer.toHexString(b[i] & 0xFF);
            }
        } catch (UnsupportedEncodingException e) {
            System.out.println("异常信息ToHexString"
                    + e.getMessage());
        }
        return str1;
    }

    public static boolean isNullOrEmpty(String str)
    {
        return str == null || str.equals("");
    }

    /**
     * 将字符串转换成16进制串，长度不足补零
     */
    public static String ToHexString(String str, int length) {
        if(str == null)
            str = "";
        String str1 = "";
        byte[] b = (byte[]) null;
        try {
            b = str.getBytes("gbk");
        } catch (UnsupportedEncodingException e) {
            System.out.println("异常信息(ControllerReport TurnISN)"
                    + e.getMessage());
        }
        System.out.println();
        int i = 0;
        int max = b.length;
        for (; i < max; i++) {
            str1 = str1 + Integer.toHexString(b[i] & 0xFF);
        }
        str1 = str1.toUpperCase();
        return turnStrLength(str1, length * 2);

    }



    public static String getStringFromHex(String str1) {
        try {
            str1 = new String(HexString2Bytes(str1), "gbk");
        } catch (UnsupportedEncodingException ex) {
            //Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        }
        return str1;
    }

    public static int getYear(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(0, 4)).intValue();
    }

    public static int getMonth(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(4, 6)).intValue();
    }

    public static int getDay(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(6, 8)).intValue();
    }

    public static int getHour(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(8, 10)).intValue();
    }

    public static int getMinute(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(10, 12)).intValue();
    }

    public static int getSeconds(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
        String year = format.format(date);
        return Integer.valueOf(year.substring(12, 14)).intValue();
    }

    public static String getDateBCDStr(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
        return format.format(date);
    }

    public static String getHexDateTime(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String hexdate = format.format(date);

        String year = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(0, 4)).intValue(), 16), 4);
        String month = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(4, 6)).intValue(), 16), 2);
        String day = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(6, 8)).intValue(), 16), 2);
        String hour = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(8, 10)).intValue(), 16), 2);
        String minute = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(10, 12)).intValue(), 16), 2);
        String seconds = turnDataLength(Integer.toString(
                Integer.valueOf(hexdate.substring(12, 14)).intValue(), 16), 2);

        return day + month + year + hour + minute + seconds;
    }

    public static byte[] getByteFromString(String datetime){
        return getByteFromString(datetime,"yyyy-MM-dd HH:mm:ss","yyyyMMddHHmmss");
    }

    public static byte[] getByteFromString(String datetime,String formattersrc,String formattertarget){
        //datetime格式：yyyy-MM-dd HH:mm:ss
        SimpleDateFormat sf = new SimpleDateFormat(formattersrc);
        Date date = null;
        try {
            date = sf.parse(datetime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        SimpleDateFormat format = new SimpleDateFormat(formattertarget);
        String hexdate = format.format(date);
        return str2Bcd(hexdate);
    }

    public static byte[] getByteString(String simno){

        return str2Bcd(simno);
    }

    public static byte[] getByteFromShortString(String datetime){
        //datetime格式：yyyy-MM-dd HH:mm:ss
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sf.parse(datetime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String hexdate = format.format(date);
        return str2Bcd(hexdate);
    }

    /**
     * @功能: BCD码转为10进制串(阿拉伯数据)
     * @参数: BCD码
     * @结果: 10进制串
     */
    public static String bcd2Str(byte[] bytes) {
        StringBuffer temp = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp
                .toString().substring(1) : temp.toString();
    }

    /**
     * @功能: BCD码转为10进制串(阿拉伯数据)
     * @参数: BCD码
     * @结果: 10进制串
     */
    public static String bcd2Str(byte bytes) {
        StringBuffer temp = new StringBuffer(2);
        temp.append((byte) ((bytes & 0xf0) >>> 4));
        temp.append((byte) (bytes & 0x0f));
        return temp.toString();
    }

    /**
     * @功能: 10进制串转为BCD码
     * @参数: 10进制串
     * @结果: BCD码
     */
    public static byte[] str2Bcd(String asc) {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        byte abt[] = new byte[len];
        if (len >= 2) {
            len = len / 2;
        }
        byte bbt[] = new byte[len];
        abt = asc.getBytes();
        int j, k;
        for (int p = 0; p < asc.length() / 2; p++) {
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
                j = abt[2 * p] - '0';
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
                j = abt[2 * p] - 'a' + 0x0a;
            } else {
                j = abt[2 * p] - 'A' + 0x0a;
            }
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
                k = abt[2 * p + 1] - '0';
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
                k = abt[2 * p + 1] - 'a' + 0x0a;
            } else {
                k = abt[2 * p + 1] - 'A' + 0x0a;
            }
            int a = (j << 4) + k;
            byte b = (byte) a;
            bbt[p] = b;
        }
        return bbt;
    }

    // 对于参数指定的日期和时间，返回自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数
    public static String getUTC(Date date) {

        //long dt = date.getTime()/1000;//

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);


        long dt = date.UTC(date.getYear(), date.getMonth(), date.getDay(),
                calendar.get(Calendar.HOUR_OF_DAY) - 8, date.getMinutes(), date.getSeconds());
        return ToHexString(dt / 1000 , 8);
    }

    public static long myround(double num) {
        BigDecimal b = new BigDecimal(num);
        num = b.setScale(2, 4).longValue();
        return (long) num;
    }

    public static Date strToDate(String str) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(str);
        } catch (ParseException e) {
            System.out.println("异常信息（strToDate）:" + e.toString());
        }
        return null;
    }

    public static String encoderStringEscape(String strEscape) {
        strEscape = strEscape.toUpperCase();
        int byteNum = strEscape.length() / 2;
        StringBuilder sb = new StringBuilder();
        for (int m = 0; m < byteNum; m++) {
            int start = m * 2;

            String temp = strEscape.substring(start, start + 2);
            if (temp.equals("5A"))
                sb.append("5A02");
            else if (temp.equals("5B"))
                sb.append("5A01");
            else if (temp.equals("5E"))
                sb.append("5E02");
            else if (temp.equals("5D"))
                sb.append("5E01");
            else
                sb.append(temp);
        }
        return sb.toString();
    }

    public static String decoderStringEscape(String strEscape) {
        strEscape = strEscape.toUpperCase();
        strEscape = strEscape.replaceAll("5A01", "5B");
        strEscape = strEscape.replaceAll("5a01", "5B");
        strEscape = strEscape.replaceAll("5A02", "5A");
        strEscape = strEscape.replaceAll("5a02", "5A");
        strEscape = strEscape.replaceAll("5E01", "5D");
        strEscape = strEscape.replaceAll("5e01", "5D");
        strEscape = strEscape.replaceAll("5E02", "5E");
        strEscape = strEscape.replaceAll("5e02", "5E");
        return strEscape;
    }


    public static Timestamp convertToTimestamp(String message) {
        long time = Long.valueOf(message, 16).longValue();

        int year = (int) (time >> 26 & 0x3F) + 2000;
        int month = (int) (time >> 22 & 0xF);
        int day = (int) (time >> 17 & 0x1F);
        int hour = (int) (time >> 12 & 0x1F);
        int minute = (int) (time >> 6 & 0x3F);
        int second = (int) (time & 0x3F);
        Calendar cd = Calendar.getInstance();
        cd.set(year, month - 1, day, hour, minute, second);
        return new Timestamp(cd.getTimeInMillis());
    }

    public static String encrypt(int key, String str) {
        int m1 = 10000000;
        int a1 = 20000000;
        int c1 = 30000000;

        byte[] b = HexString2Bytes(str);
        int size = b.length;
        if (key == 0)
            key = 1;
        for (int i = 0; i < size; i++) {
            key = a1 * (key % m1) + c1;
            int tmp49_47 = i;
            byte[] tmp49_45 = b;
            tmp49_45[tmp49_47] = ((byte) (tmp49_45[tmp49_47] ^ (char) (key >> 20) & 0xFF));
        }
        return ToHexString(b);
    }

    public static void main(String[] args) {

//        short t = -23;
//        String str = Integer.toHexString(t &0xff);
//
//        System.out.println(str);
//
//        Date date = new Date();
//
//        System.out.println(date.toString());
//        System.out.println(date.getYear()+ "," + date.getMonth()+ "," + date.getDay()+ "," +
//                date.getHours()+ "," + date.getMinutes()+ "," + date.getSeconds());
//        long dt = Date.UTC(date.getYear(), (date.getMonth() ), 29,
//                date.getHours() - 8, date.getMinutes(), date.getSeconds());
//
//        Date date1 = new Date(dt);

//        String aaa = "2017-07-08 12:12:14";
//        byte[] bytes = getByteFromString(aaa);
//        System.out.println(bytes);

         //byte a = (byte)0x21;
         //System.out.println(bcd2Str(a)+":"+bcd2Str((byte) 0x00));
        //System.out.println(getMsgHead((byte)0x88, (byte)0x88, (byte)0x88));
        //System.out.println(BinaryUtil.ToHexFormatString(str2Bcd("13625190030")));
        //System.out.println(BinaryUtil.ToHexFormatString(createMsgHead(8947848,3)));
        boolean[] b = new boolean[]{true,false,false,true,false,false,false,true};
        System.out.println(groupByte(b));
    }

    /**
     * 将标识字符的转义字符还原
     * @param data
     * @return
     */
    public static byte[] UnEscape(byte[] data){
        List list = new ArrayList();
        for(int i=0;i<data.length;i++){
            if(data[i] == 0x7D){
                if(data[i+1] == 0x01){
                    list.add((byte)0x7D);
                    i++;
                }else if (data[i+1]==0x02){
                    list.add((byte)0x7E);
                    i++;
                }
            }else{
                list.add(data[i]);
            }
        }
        return get(list);
    }

    public static byte[] get(List list){
        byte[] result = new byte[list.size()];
        for(int i=0;i<list.size();i++){
            result[i] = Byte.parseByte(list.get(i).toString());
        }
        return result;
    }

    public static byte[] Escape(byte[] data){
        List list = new ArrayList();
        for(int i=0;i<data.length;i++){
            if(data[i] == 0x7D){
                list.add((byte)0x7D);
                list.add((byte)0x01);
            }else if(data[i] == 0x7E){
                list.add((byte)0x7D);
                list.add((byte)0x02);
            }else{
                list.add(data[i]);
            }
        }
        return get(list);
    }
}
